package com.zsp.coupon.service.imp;

import com.google.common.base.Stopwatch;
import com.zsp.coupon.constant.Constant;
import com.zsp.coupon.dao.CouponTemplateDao;
import com.zsp.coupon.entity.CouponTemplate;
import com.zsp.coupon.service.IAsyncService;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Component
public class AsyncServiceImpl implements IAsyncService {

    /** CouponTemplate Dao */
    private final CouponTemplateDao couponTemplateDao;
    /** 注入 Redis 模板类 */
    private final StringRedisTemplate redisTemplate;

    @Autowired
    public AsyncServiceImpl(CouponTemplateDao templateDao,
                            StringRedisTemplate redisTemplate) {
        this.couponTemplateDao = templateDao;
        this.redisTemplate = redisTemplate;
    }


    /**
     * <h2>根据模板异步的创建优惠券码</h2>
     * @param template {@link CouponTemplate} 优惠券模板实体
     */
    @Async("getAsyncExecutor")
    @Override
    @SuppressWarnings("all")
    public void asyncConstructCouponByTemplate(CouponTemplate template) {
        Stopwatch watch = Stopwatch.createStarted();
        //生成优惠卷码
        Set<String> couponCode=buildCouponCode(template);

        // imooc_coupon_template_code_1
        String redisKey = String.format("%s%s",
                Constant.RedisPrefix.COUPON_TEMPLATE, template.getId().toString());
        System.out.println("Push CouponCode To Redis: {}"+
                redisTemplate.opsForList().rightPushAll(redisKey, couponCode));
        template.setAvailabe(true);
        couponTemplateDao.save(template);

        watch.stop();
        System.out.println("Construct CouponCode By Template Cost: {}ms"+
                watch.elapsed(TimeUnit.MILLISECONDS));
        // TODO 发送短信或者邮件通知优惠券模板已经可用
        System.out.println("CouponTemplate({}) Is Available!"+template.getId());

    }

    /**
     * <h2>构造优惠券码</h2>
     * 优惠券码(对应于每一张优惠券, 18位)
     *  前四位: 产品线 + 类型
     *  中间六位: 日期随机(190101)
     *  后八位: 0 ~ 9 随机数构成
     * @param  {@link CouponTemplate} 实体类
     * @return Set<String> 与 template.count 相同个数的优惠券码
     * */
 private Set<String> buildCouponCode(CouponTemplate template){
     Stopwatch watch = Stopwatch.createStarted();

     Set<String> result=new HashSet<>(template.getCount());
     //前四位
        String pre4= template.getProdcutLine().getCode().toString()
                    + template.getCategory().getCode();
     String date = new SimpleDateFormat("yyMMdd")
             .format(template.getCreateTime());
     for (int i = 0; i != template.getCount(); ++i) {
         result.add(pre4 + buildCouponCodeSuffix14(date));
     }
     while (result.size() < template.getCount()) {
         result.add(pre4 + buildCouponCodeSuffix14(date));
     }

     assert result.size() == template.getCount();
     watch.stop();
     System.out.println("Build Coupon Code Cost: {}ms"+
             watch.elapsed(TimeUnit.MILLISECONDS));
     return result;
 }


    /**
     * <h2>构造优惠券码的后 14 位</h2>
     * @param date 创建优惠券的日期
     * @return 14 位优惠券码
     * */
    private String buildCouponCodeSuffix14(String date) {

        char [] base=new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9'};
        //中间6位
        List<Character> charas=date.chars()
                .mapToObj(e ->(char) e).collect(Collectors.toList());
        Collections.shuffle(charas);
        String mid6=charas.stream()
                .map(Object::toString).collect(Collectors.joining());

        //后八位
        String suffix8 = RandomStringUtils.random(1,base)
                +RandomStringUtils.randomNumeric(7);
        return mid6+suffix8;
    }

}
